package edu.kit.ksri.db.mturk.standaloneutils.resultanalyzers;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashMap;

import edu.kit.ksri.db.mturk.utils.FileUtils;
import edu.kit.ksri.db.mturk.var.StaticInformation;

/**
 * Copyright (c) 2010-2011 Karlsruhe Institute of Technology (KIT), Germany
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 * 
 * --------------------------------------------------------------------------
 * 
 * Software: CSP/WMV tool for dynamic quality management of microtasks
 * http://www.ksri.kit.edu/Upload/Users/PeopleClouds/HCOMP2011_An_extendable_toolkit_for_managing_quality_of_human-based_eServices.pdf
 * 
 * Organization: Karlsruhe Institute of Technology (KIT), Germany
 * http://www.kit.edu
 * 
 * Project: PeopleClouds project of the Karlsruhe Service Research Institute(KSRI)
 * http://www.ksri.kit.edu/Default.aspx?PageId=818
 * 
 * Contributing authors: David Bermbach, Sandra Rath, Pascal Wichmann, Robert Kern
 */
public class ResultAnalyzer {

	private static final String resultfolder = StaticInformation.resultOutputDirectoryDuplicate;
	private static final String goldstandardfile = StaticInformation.qualificationGoldStandardFile;

	private static final HashMap<String, ArrayList<ExportedResult>> allResults = new HashMap<String, ArrayList<ExportedResult>>();

	private static final HashMap<String, String> correctResults = new HashMap<String, String>();

	private static final HashMap<String, String> goldstandards = new HashMap<String, String>();

	private static final HashMap<String, MergedResult> mergedResults = new HashMap<String, MergedResult>();

	public static void main(String[] args) throws Exception {
		File folder = new File(resultfolder);
		File[] allFiles = folder.listFiles(getFilterForAllResults());
		File[] correctFiles = folder.listFiles(getFilterForCorrectResults());
		for (File f : allFiles)
			parseAllFiles(f);
		for (File f : correctFiles)
			parseCorrectFiles(f);
		parseGoldstandards();
		mergeResults();
		exportMergedResults();
	}

	/**
	 * 
	 */
	private static void exportMergedResults() {
		StringBuffer b = new StringBuffer(MergedResult.getCSVHeaders() + "\n");
		for (MergedResult m : mergedResults.values()) {
			b.append(m.toCSVString() + "\n");
		}
		if (FileUtils.writeToFile(b.toString(), resultfolder
				+ "/MergedResults.csv"))
			System.out.println("Exporting merged results successful.");
		else
			System.out.println("Error while exporting merged results.");

	}

	/**
	 * 
	 */
	private static void mergeResults() {
		for (String id : goldstandards.keySet()) {
			MergedResult m = new MergedResult();
			m.hitid = id;
			m.goldstandard = goldstandards.get(id);
			if (m.goldstandard == null)
				m.goldstandard = "N/A";
			m.correctresult = correctResults.get(id);
			if (m.correctresult == null)
				m.correctresult = "N/A";
			ArrayList<ExportedResult> temp = allResults.get(id);
			if (temp != null) {
				for (ExportedResult e : temp) {
					m.answers.add(e.ocrResult);
				}
			}
			mergedResults.put(id, m);
			System.out.println("Done merging: " + m);
		}
	}

	/**
	 * 
	 */
	private static void parseGoldstandards() {
		try {
			BufferedReader gold = new BufferedReader(new FileReader(
					goldstandardfile));
			BufferedReader mapping = new BufferedReader(new FileReader(
					resultfolder + "/hitidmapping.csv"));
			String gs = "", map = mapping.readLine();// skip first line
			int pos = 0;
			while (true) {
				gs = gold.readLine();
				map = mapping.readLine();
				if (gs == null || map == null)
					break;
				gs = gs.trim();
				map = map.trim();
				// System.out.println("map="+map);
				pos = map.indexOf(";") + 2;
				map = map.substring(pos, map.length() - 2);
				// System.out.println("map="+map);
				System.out.println("Parsed Goldstandard: [hitid=" + map
						+ ", goldstandard=" + gs + "]");
				goldstandards.put(map, gs);
			}
		} catch (Exception e) {
			System.out.println("Error while parsing gold standards: " + e);
		}
	}

	/**
	 * parses an "correct.HITID.xml" file and puts its contents into allResults
	 * 
	 * @param f
	 * 
	 */
	private static void parseCorrectFiles(File f) {
		String hitid = "";
		String answer = "";
		try {
			BufferedReader br = new BufferedReader(new FileReader(f));
			String content = "", line = br.readLine();
			while (line != null) {
				content += line;
				line = br.readLine();
			}
			// System.out.println(content + "\n\n");
			int start = content.indexOf("hitid=") + 7;
			content = content.substring(start);
			int end = content.indexOf("\"");
			hitid = content.substring(0, end);
			// System.out.println(hitid);

			start = content.indexOf("<FreeText>") + 10;
			content = content.substring(start);
			end = content.indexOf("</FreeText>");
			answer = content.substring(0, end);
			// System.out.println(answer);
			content = content.substring(end);
			System.out.println("Parsed correct result: [hitid=" + hitid
					+ ", answer=" + answer + "]");
			correctResults.put(hitid, answer);

		} catch (Exception e) {
			System.out.println("Error while reading file " + f);
		}

	}

	/**
	 * parses an "all.HITID.xml" file and puts its contents into allResults
	 * 
	 * @param f
	 * 
	 */
	private static void parseAllFiles(File f) {
		ArrayList<ExportedResult> res = new ArrayList<ExportedResult>();
		String hitid = "";
		try {
			BufferedReader br = new BufferedReader(new FileReader(f));
			String content = "", line = br.readLine();
			while (line != null) {
				content += line;
				line = br.readLine();
			}
			// System.out.println(content + "\n\n");
			int start = content.indexOf("hitid=") + 7;
			content = content.substring(start);
			int end = content.indexOf("\"");
			hitid = content.substring(0, end);
			// System.out.println(hitid);
			start = content.indexOf("numberOfResults=") + 17;
			content = content.substring(start);
			end = content.indexOf("\"");
			int number = Integer.parseInt(content.substring(0, end));
			// System.out.println(number);
			for (int i = 0; i < number; i++) {
				// parse single results
				start = content.indexOf("worker=") + 8;
				content = content.substring(start);
				end = content.indexOf("\"");
				String workerid = content.substring(0, end);
				// System.out.println(workerid);
				start = content.indexOf("<FreeText>") + 10;
				content = content.substring(start);
				end = content.indexOf("</FreeText>");
				String answer = content.substring(0, end);
				// System.out.println(answer);
				content = content.substring(end);
				ExportedResult e = new ExportedResult();
				e.hitid = hitid;
				e.ocrResult = answer;
				e.workerid = workerid;
				res.add(e);
				System.out.println("Parsed instance of " + e);
			}

		} catch (Exception e) {
			System.out.println("Error while reading file " + f);
		}

		allResults.put(hitid, res);
	}

	/**
	 * 
	 * @return a {@link FilenameFilter} for files starting with "correct."
	 */
	public static FilenameFilter getFilterForCorrectResults() {
		FilenameFilter filter = new FilenameFilter() {

			public boolean accept(File dir, String name) {
				if (name.trim().startsWith("correct."))
					return true;
				return false;
			}
		};
		return filter;
	}

	/**
	 * 
	 * @return a {@link FilenameFilter} for files starting with "all."
	 */
	public static FilenameFilter getFilterForAllResults() {
		FilenameFilter filter = new FilenameFilter() {

			public boolean accept(File dir, String name) {
				if (name.trim().startsWith("all."))
					return true;
				return false;
			}
		};
		return filter;
	}

}
